package com.letv.recorder.ui.base;

import android.app.Dialog;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.FrameLayout;
import android.widget.Toast;

import com.letv.recorder.callback.ISurfaceCreatedListener;
import com.letv.recorder.callback.PublishListener;
import com.letv.recorder.controller.CameraSurfaceView;
import com.letv.recorder.controller.Publisher;
import com.letv.recorder.ui.RecorderBottomView;
import com.letv.recorder.ui.RecorderDialogBuilder;
import com.letv.recorder.ui.RecorderTopFloatView;
import com.letv.recorder.ui.RecorderView;
import com.letv.recorder.ui.logic.RecorderConstance;
import com.letv.recorder.ui.mobile.RecorderTopFloatMobileView;
import com.letv.recorder.util.LeLog;
import com.letv.recorder.util.NetworkUtils;

public abstract class RecorderSkinBase {
	protected static final String TAG = "CameraView2";
	
	protected final static int RE_TRY_NUM = 0;
	protected boolean isReTry = false;
	protected int reTry = 0;

	/**
	 * UI模块(顶部栏，底部栏,机位选择dialog,matherBoard视图)
	 */
	protected RecorderView rv;
	private RecorderTopFloatView topFloatView;
	private RecorderBottomView bottomView;
	private Dialog dialog;
	private Dialog loadDialog;

	protected Publisher publisher;

	protected Handler handler = new Handler();
	protected Context context;
	protected String streamName;
	public boolean isResume = false;
	private int time;
	private volatile int video_lose = 0;
	private volatile int audio_lose = 0;

	/**
	 * 人数统计
	 */
	// TODO: 暂时没有实现，所以关闭
	// private CountPeopleTimer mCountPeopleTimer;

	protected int orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;

	/**
	 * 构建一个默认皮肤
	 * 
	 * @param context
	 *            上下文
	 * @param rv
	 *            皮肤rootView
	 */
	public void build(Context context, RecorderView rv, int orientation) {
		this.rv = rv;
		this.context = context;
		this.orientation = orientation;
		setCameraView(new CameraSurfaceView(context));
		initCameraPreView(getCameraView());
		initObserver();
	}

	/**
	 * 于推流器绑定
	 * 
	 * @param publisher
	 */
	public void BindingPublisher(final Publisher publisher) {
		this.publisher = publisher;
		rv.buildPublisher(publisher);
		setPublisherListerner();
		/**
		 * 上层按钮点击事件
		 */
		getTopFloatView().getTopSubject().addObserver(publisher.getVideoRecordDevice());
		getBottomView().getBottomSubject().addObserver(publisher.getVideoRecordDevice());
		getBottomView().buildPublisher(publisher);
		getTopFloatView().buildPublisher(publisher);
		publisher.getVideoRecordDevice().bindingGLView((CameraSurfaceView) getCameraView());
		publisher.getVideoRecordDevice().setSurfaceCreatedListener(new ISurfaceCreatedListener() {
			@Override
			public void onGLSurfaceCreatedListener() {
				publisher.getVideoRecordDevice().start();
				if(isResume){
					isResume = false;
					LeLog.d("HOME键回来,重新开始推流");
					rv.publish();
				}
			}
		});
	}

	/**
	 * 设置推流回调
	 */
	private void setPublisherListerner() {
		if (publisher != null) {
			publisher.setPublishListener(new PublishListener() {
				@Override
				public void onPublish(int code, final String msg, final Object... objs) {
					LeLog.d(TAG, "[callback] code:" + code);
					switch (code) {
					// case RecorderConstance.recorder_start_ok:
					case RecorderConstance.RECORDER_OPEN_URL_SUCESS:
						LeLog.d("RTMP 地址打开成功");
						break;
					case RecorderConstance.RECORDER_OPEN_URL_FAILED:
						handler.post(new Runnable() {
							@Override
							public void run() {
								rv.setClickable();
								dimssLoadDialog();
								if(isReTry){
									reTryPublisher();
								}else{
									RecorderSkinBase.this.getBottomView().reset();
									LeLog.w("无法连接到推流地址");
									if(dialog != null && dialog.isShowing()){
										dialog.dismiss();
										dialog = null;
									}
									dialog = RecorderDialogBuilder.showCommentDialog(context, "无法连接推流服务器","我知道了",null, new OnClickListener() {
										
										@Override
										public void onClick(View v) {
											dialog.dismiss();
											dialog = null;
										}
									}, null);
									stopPublishWithUI();
								}
							}
						});
						break;
					case RecorderConstance.RECORDER_PUSH_FIRST_SIZE:
						handler.post(new Runnable() {
							@Override
							public void run() {
								LeLog.d("收到第一针推流成功的事件,此时是否进入到后台?"+isResume);
								if(isResume) return;
								rv.setClickable();
								mHandler.postDelayed(runnable,30*1000);
								((RecorderTopFloatMobileView)getTopFloatView()).setTime(time);
								((RecorderTopFloatMobileView)getTopFloatView()).startRecorderView();
								reTry = 0;
								dimssLoadDialog();
							}
						});
						break;
					case RecorderConstance.RECORDER_PUSH_ERROR:
						handler.post(new Runnable() {
							@Override
							public void run() {
								rv.setClickable();
								dimssLoadDialog();
								isReTry = true;
								LeLog.w("推流错误");
							    reTryPublisher();
							}
						});
						break;
					case RecorderConstance.LIVE_STATE_NEED_RECORD:
						handler.post(new Runnable() {
							@Override
							public void run() {
								boolean isNeedRecord = (Boolean) objs[0];
								Bundle bundle=new Bundle();
								if(isNeedRecord){
									bundle.putInt("flag", RecorderConstance.enable_rec);
								}else{
									bundle.putInt("flag", RecorderConstance.disable_rec);
								}
								rv.getStartSubject().notifyObserverPlus(bundle);// 通知观察者
							}
						});
						break;
					case RecorderConstance.LIVE_STATE_CANCEL_ERROR:
					case RecorderConstance.LIVE_STATE_END_ERROR:
						handler.post(new Runnable() {
							@Override
							public void run() {
								LeLog.w("直播还没有到开始");
								dimssLoadDialog();
								dialog = RecorderDialogBuilder.showCommentDialog(context, "直播已结束，可再去创建您的直播活动","我知道了",null, new OnClickListener() {
									
									@Override
									public void onClick(View v) {
										dialog.dismiss();
										dialog = null;
									}
								}, null);
							}
						});
						break;
					case RecorderConstance.LIVE_STATE_NOT_STARTED_ERROR:
						handler.post(new Runnable() {
							@Override
							public void run() {
								Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
								LeLog.w("直播还没有到开始");
								dimssLoadDialog();
							}
						});
						break;
					case RecorderConstance.LIVE_STATE_TIME_REMAINING:
					case RecorderConstance.RECORDER_PUSH_AUDIO_PACKET_LOSS_RATE:
						audio_lose ++;
						break;
					case RecorderConstance.RECORDER_PUSH_VIDEO_PACKET_LOSS_RATE:
						video_lose ++;
						break;
					case RecorderConstance.LIVE_STATE_PUSH_COMPLETE:
						handler.post(new Runnable() {
							@Override
							public void run() {
								Toast.makeText(context, msg, Toast.LENGTH_SHORT) .show();
								Bundle bundle = new Bundle();
								bundle.putInt("flag", RecorderConstance.recorder_stop);
								rv.getStartSubject().notifyObserverPlus(bundle);
								rv.reSetStartBtn(false);
								RecorderSkinBase.this.getBottomView().reset();
								dimssLoadDialog();
							}
						});
						break;
					case RecorderConstance.RECORDER_PUSH_STOP_SUCCESS:
						handler.post(new Runnable() {
							@Override
							public void run() {
								rv.reSetStartBtn(false);
								rv.setClickable();
								RecorderSkinBase.this.getBottomView().reset();
								dimssLoadDialog();
							}
						});
						break;
					}
				}
			});
		}
	}
	/**
	 * 重试推流
	 */
	protected void reTryPublisher(){
		LeLog.d("是否开启重试:"+isReTry+"当前重试次数:"+reTry+",当前网络状态:"+NetworkUtils.getNetType(context));
		Bundle bundle = new Bundle();
		reTry++;
		if(!isReTry || reTry > RE_TRY_NUM || NetworkUtils.getNetType(context) == null){
			isReTry = false;
			reTry = 0;
			bundle.putInt("flag", RecorderConstance.recorder_stop);
			rv.getStartSubject().notifyObserverPlus(bundle);
			rv.reSetStartBtn(false);
			RecorderSkinBase.this.getBottomView().reset();
			dimssLoadDialog();
			if(dialog != null && dialog.isShowing()){
				dialog.dismiss();
				dialog = null;
			}
			dialog = RecorderDialogBuilder.showCommentDialog(context, ((NetworkUtils.getNetType(context) == null)?"网络异常,":"")+"无法连接推流服务器","我知道了",null, new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					dialog.dismiss();
					dialog = null;
				}
			}, null);
		}else{
			RecorderSkinBase.this.getBottomView().reSetRunnable();
			LeLog.w("开始重试，当前重试次数:"+reTry);
			bundle.putInt("flag", RecorderConstance.angle_request);
			rv.getStartSubject().notifyObserverPlus(bundle);
		}
	}
	/**
	 * 组装ui
	 * 
	 * @param cameraView
	 */
	protected abstract void initCameraPreView(FrameLayout cameraView);

	protected void showLoadDialog() {
		loadDialog = RecorderDialogBuilder.showLoadDialog(context,"正在急速加载中，请稍等");
	}

	protected void dimssLoadDialog() {
		if (loadDialog != null && loadDialog.isShowing()) {
			loadDialog.dismiss();
		}
	}

	/**
	 * UI响应注册
	 */
	protected abstract void initObserver();

	/**
	 * 对几位进行处理
	 */
	protected abstract void handleMachine();

	/**
	 * activity(fragment)生命周期onResume时调用次方法
	 */
	int count = 0;
	public void onResume() {
		getCameraView().onResume();
		registerNetworkChange();
	}

	/**
	 * activity(fragment)生命周期onPause时调用次方法
	 */
	public void onPause() {
		if(publisher.isRecording()){
			isResume = true;
			time = ((RecorderTopFloatMobileView)getTopFloatView()).getTime();
		}else{
			isResume = false;
			time = 0;
		}
		getCameraView().onPause();
		publisher.getVideoRecordDevice().stop();
		if(getBottomView() != null){
			getBottomView().onPause();
		}
		dimssLoadDialog();
		unregisterNetworkChange();
		stopPublishWithUI();
	}

	/**
	 * activity(fragment)生命周期onDestroy时调用次方法
	 */
	public void onDestroy() {
		if (publisher != null) {
			publisher.release();
			time = 0;
			isResume = false;
		}
	}

	/**
	 * 停止推流，同时更新UI
	 */
	private void stopPublishWithUI() {
		if (rv != null) {
			rv.stopAuto();
		}
	}

	protected RecorderBottomView getBottomView() {
		return bottomView;
	}

	protected void setBottomView(RecorderBottomView bottomView) {
		this.bottomView = bottomView;
	}

	protected RecorderTopFloatView getTopFloatView() {
		return topFloatView;
	}

	protected void setTopFloatView(RecorderTopFloatView topFloatView) {
		this.topFloatView = topFloatView;
	}


//	@Override
//	public void surfaceCreated(SurfaceHolder arg0) {
//		if (publisher.getVideoRecordDevice() != null) {
//			publisher.getVideoRecordDevice().bindingSurface(arg0);
//			publisher.getVideoRecordDevice().start();
//		}
//	}
//
//	@Override
//	public void surfaceDestroyed(SurfaceHolder arg0) {
//		if (publisher.getVideoRecordDevice() != null) {
//			publisher.getVideoRecordDevice().stop();
//		}
//	}

	/**
	 * 选择机位
	 */
	protected abstract void selectMachine(int numFlag);
	/**
	 * 注册网络监听
	 */
	private void registerNetworkChange() {
		IntentFilter filter = new IntentFilter();
		filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
		filter.setPriority(1000);
		context.registerReceiver(networkChangeReceiver, filter);
		//同时注册电话监听
		IntentFilter phoneFilter = new IntentFilter();
		phoneFilter.addAction("android.intent.action.PHONE_STATE");
		phoneFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
		context.registerReceiver(phoneReceiver,phoneFilter);
	}

	/**
	 * 取消网络监听
	 */
	private void unregisterNetworkChange() {
		context.unregisterReceiver(networkChangeReceiver);
		context.unregisterReceiver(phoneReceiver);
	}

	public CameraSurfaceView getCameraView() {
		return cameraView;
	}

	public void setCameraView(CameraSurfaceView cameraView) {
		this.cameraView = cameraView;
	}

	private NetworkChangeReceiver networkChangeReceiver = new NetworkChangeReceiver();
	private PhoneReceiver phoneReceiver = new PhoneReceiver();

	private CameraSurfaceView cameraView;

	private class PhoneReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			if(!intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){
				//监听到来电情况.如果此时正在推流，那么立即断开推流
				TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
				if(!(tm.getCallState() == TelephonyManager.CALL_STATE_RINGING)) return;
				LeLog.d("监听到来电状态，当前是否在推流："+(publisher != null && publisher.isRecording()));
				if(publisher != null && publisher.isRecording()){
					rv.stopRecorder();
					rv.reSetStartBtn(false);
					rv.setClickable();
					RecorderSkinBase.this.getBottomView().reset();
				}
			}
		}
	}
	private class NetworkChangeReceiver extends BroadcastReceiver {
		private Bundle bundle = new Bundle();

		@Override
		public void onReceive(final Context context, Intent intent) {
			//TODO: 这里只监听一种情况，就是 WIFI转3G 4G的情况。如果此时推流还没有断掉，那么我就需要手动掐断，然后给用户提示
			ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
//			LeLog.w("网络发生变化,当前网络是:"+ ((networkInfo==null)?null:networkInfo.getTypeName()) +",网络是否可用:"+ ((networkInfo==null)?null:networkInfo.getState())+"是否在继续推流:"+publisher.isRecording());
//			if(!publisher.isRecording() || (NetworkUtils.getNetType(context) != null && !NetworkUtils.isWifiNetType(context))) return;
			if(!publisher.isRecording()) return;
			rv.stopRecorder();
			rv.reSetStartBtn(false);
			rv.setClickable();
			RecorderSkinBase.this.getBottomView().reset();
			if(dialog != null && dialog.isShowing()){
				dialog.dismiss();
				dialog = null;
			}
			dialog = RecorderDialogBuilder.showNoNetworkWarningDialog(context, new OnClickListener() {
				@Override
				public void onClick(View v) {
					dialog.dismiss();
					dialog = null;
				}
			});
			return;
		}
	}
	public void setStreamName(String streamName) {
		this.streamName = streamName;
	}
	private Handler mHandler = new Handler();
	private Runnable runnable = new Runnable() {
		@Override
		public void run() {
			if(publisher.isRecording()){
				if(video_lose > 3 || audio_lose > 3){
					Toast.makeText(context,"当前网络较差,请更换网络环境",Toast.LENGTH_SHORT).show();
				}
				video_lose = 0;
				audio_lose = 0;
				mHandler.postDelayed(runnable,30*1000);
			}
		}
	};
	
}
